package com.platform.modules.wallet.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.platform.common.constant.ApiConstant;
import com.platform.common.enums.YesOrNoEnum;
import com.platform.common.exception.BaseException;
import com.platform.common.utils.redis.RedisUtils;
import com.platform.common.web.service.impl.BaseServiceImpl;
import com.platform.modules.chat.domain.ChatGroupInfo;
import com.platform.modules.chat.domain.ChatUser;
import com.platform.modules.chat.service.ChatGroupInfoService;
import com.platform.modules.chat.service.ChatUserService;
import com.platform.modules.chat.vo.ChatVo01;
import com.platform.modules.chat.vo.ChatVo02;
import com.platform.modules.wallet.dao.WalletRedPacketDao;
import com.platform.modules.wallet.domain.Wallet;
import com.platform.modules.wallet.domain.WalletAccount;
import com.platform.modules.wallet.domain.WalletRedPacket;
import com.platform.modules.wallet.domain.WalletRedPacketSub;
import com.platform.modules.wallet.enums.AccountTypeEnum;
import com.platform.modules.wallet.enums.RedPacketLuckEnum;
import com.platform.modules.wallet.enums.RedPacketStatusEnum;
import com.platform.modules.wallet.enums.RedPacketTypeEnum;
import com.platform.modules.wallet.service.WalletAccountService;
import com.platform.modules.wallet.service.WalletRedPacketService;
import com.platform.modules.wallet.service.WalletRedPacketSubService;
import com.platform.modules.wallet.service.WalletService;
import com.platform.modules.wallet.utils.RandSplitNumUtils;
import com.platform.modules.wallet.utils.TransferUtils;
import com.platform.modules.wallet.vo.AccountVo01;
import com.platform.modules.wallet.vo.RedPacketSubVo;
import com.platform.modules.wallet.vo.RedPacketVo;
import com.platform.modules.wallet.vo.RedPacketVo01;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;

@Slf4j
@Service("walletRedPacketService")
public class WalletRedPacketServiceImpl extends BaseServiceImpl<WalletRedPacket> implements WalletRedPacketService {

    @Autowired
    private RedisUtils redisUtils;
    @Resource
    private WalletRedPacketDao walletRedPacketDao;
    @Resource
    private ChatUserService chatUserService;
    @Resource
    private WalletService walletService;
    @Resource
    private WalletAccountService walletAccountService;
    @Resource
    private WalletRedPacketSubService walletRedPacketSubService;
    @Resource
    private ChatGroupInfoService groupInfoService;
    @Autowired
    private TransferUtils transferUtils;

    @Autowired
    public void setBaseDao() {
        super.setBaseDao(walletRedPacketDao);
    }

    @Override
    public WalletRedPacket transfer(ChatVo01 chatVo, Long userId) {

        Wallet wallet = walletService.getWallet(userId);
        // 当前用户
        ChatUser cu = chatUserService.getById(wallet.getUserId());
        transferUtils.verifySend(chatVo.getContent(), wallet, cu);

        RedPacketVo01 redPacketVO01 = new RedPacketVo01();
        redPacketVO01.setToId(chatVo.getUserId());
        redPacketVO01.setContent(chatVo.getContent());
        redPacketVO01.setUserId(userId);

        return createRedPacket(redPacketVO01);
    }

    @Override
    public WalletRedPacket transfer(ChatVo02 chatVo, Long userId) {

        Wallet wallet = walletService.getWallet(userId);
        // 当前用户
        ChatUser cu = chatUserService.getById(userId);
        transferUtils.verifySend(chatVo.getContent(), wallet, cu);

        RedPacketVo01 redPacketVO01 = new RedPacketVo01();
        redPacketVO01.setToId(chatVo.getGroupId());
        redPacketVO01.setContent(chatVo.getContent());
        redPacketVO01.setUserId(userId);

        return createRedPacket(redPacketVO01);
    }

    @Override
    public WalletRedPacket createRedPacket(RedPacketVo01 vo) {

        JSONObject json = JSONUtil.parseObj(vo.getContent());
        int amount = new BigDecimal(json.getStr("amount")).multiply(BigDecimal.valueOf(100)).intValue();
        String queryId = json.getStr("queryId");
        RedPacketTypeEnum type = json.get("type", RedPacketTypeEnum.class);
        Integer count = json.getInt("count");
        String name = json.getStr("name");

        RedPacketVo redPacketVo = new RedPacketVo();
        redPacketVo.setFromId(vo.getUserId());
        redPacketVo.setToId(vo.getToId());
        redPacketVo.setAmount(amount);
        redPacketVo.setQueryId(queryId);
        redPacketVo.setType(type);
        redPacketVo.setCount(count);
        redPacketVo.setName(name);

        return create(redPacketVo);
    }

    @Override
    public boolean openRedPacket(String id, Long userId) {

        WalletRedPacket redPacket = getByQueryId(id);

        if (!RedPacketStatusEnum.SUCCESS.equals(redPacket.getStatus())) {
            throw new BaseException("红包转态异常，Status:" + redPacket.getStatus());
        }

        if (RedPacketTypeEnum.GROUP.equals(redPacket.getType())) {

            String key = ApiConstant.WALLET_RED_PACKET + id;
            String value = String.valueOf(userId);

            if (redisUtils.sSize(key).intValue() >= redPacket.getCount()) {
                throw new BaseException("手慢了，红包派完了");
            }

            if (redisUtils.sIsMember(key, value)) {
                throw new BaseException("红包已接收过了");
            }

            // 查询群明细
            ChatGroupInfo groupInfo = groupInfoService.getGroupInfo(redPacket.getToId(), userId, YesOrNoEnum.NO);
            if (groupInfo == null || YesOrNoEnum.YES.equals(groupInfo.getKicked())) {
                throw new BaseException("群权限限制");
            }
        }

        boolean open = walletRedPacketSubService.openRedPacket(redPacket.getId(), userId);

        if (open) {//开包成功
            return true;
        } else {
            throw new BaseException("红包已抢完");
        }
    }

    @Override
    public boolean findToIdByUserId(Long id, Long userId) {

        List<WalletRedPacketSub> walletRedPacketSubs = walletRedPacketSubService.queryByToId(id, userId);

        if (walletRedPacketSubs.size() > 0) {
            return true;
        }

        return false;
    }

    @Override
    public List<WalletRedPacketSub> querySubSuccessList(Long id) {
        return walletRedPacketSubService.queryByStatusSuccess(id);
    }

    @Override
    public List<WalletRedPacketSub> querySubInitList(Long id) {
        return walletRedPacketSubService.queryByStatusInit(id);
    }

    @Override
    public WalletRedPacket getByQueryId(String queryId) {
        WalletRedPacket redPacket = new WalletRedPacket()
                .selectOne(
                        new LambdaQueryWrapper<WalletRedPacket>()
                                .eq(WalletRedPacket::getQueryId, queryId));
        if (redPacket == null) {
            throw new BaseException("对象不存在");
        }
        return redPacket;

    }

    @Transactional(rollbackFor = Exception.class)
    public WalletRedPacket create(RedPacketVo vo) {

        WalletRedPacket bean = getBean();
        bean.setQueryId(vo.getQueryId());
        bean.setAmount(vo.getAmount());
        bean.setFromId(vo.getFromId());
        bean.setToId(vo.getToId());
        bean.setType(vo.getType());
        bean.setName(vo.getName());
        if (RedPacketTypeEnum.SINGLE.equals(vo.getType())) {
            bean.setCount(new Integer(1));
        } else {
            bean.setCount(vo.getCount());
        }
        add(bean);

        List<Integer> list = RandSplitNumUtils.genRandList(bean.getAmount(), bean.getCount(), 1, bean.getAmount());
        Comparator<Integer> comparator = Comparator.comparing(Integer::intValue);
        int max = list.stream().max(comparator).get().intValue();
        for (Integer integer : list) {

            int amount = integer.intValue();
            RedPacketSubVo subVo = new RedPacketSubVo();
            subVo.setRedpacketId(bean.getId());
            subVo.setAmount(amount);
            subVo.setFromId(bean.getFromId());
            if (max == integer) {
                subVo.setBestLuck(RedPacketLuckEnum.YES);
            } else {
                subVo.setBestLuck(RedPacketLuckEnum.NO);
            }
            walletRedPacketSubService.createRedPacketSub(subVo);
        }

        AccountVo01 accountVo = new AccountVo01();
        accountVo.setOtherId(bean.getId());
        accountVo.setAmount(vo.getAmount());
        accountVo.setType(AccountTypeEnum.RED_PACKET_OUT);
        accountVo.setUserId(vo.getFromId());

        WalletAccount account = walletAccountService.createRecord(accountVo, WalletAccountService.NEGATIVE);

        walletAccountService.successRecord(account.getId());//完成账本记录
        synchronized(this){
            walletService.subtract(accountVo.getAmount(), account.getUserId());//减掉余额
        }
        successOut(bean.getId());//完成出账（出账）
        return bean;
    }

    /**
     * 完成转出状态
     *
     * @param id
     */
    private void successOut(Long id) {
        WalletRedPacket walletRedPacket = findById(id);
        walletRedPacket.setStatus(RedPacketStatusEnum.SUCCESS);
        walletRedPacket.setSuccessTime(DateUtil.date());
        updateById(walletRedPacket);
    }

    private WalletRedPacket getBean() {
        return new WalletRedPacket()
                .setCreateTime(DateUtil.date())
                .setStatus(RedPacketStatusEnum.INIT);
    }
}
